package zack.project.infrastructure.persistent.repository;

import zack.project.domain.rebate.adapter.repository.IBehaviorRebateRepository;
import zack.project.domain.rebate.model.aggregate.BehaviorRebateAggregate;
import zack.project.domain.rebate.model.entity.BehaviorRebateOrderEntity;
import zack.project.domain.rebate.model.entity.TaskEntity;
import zack.project.domain.rebate.model.valobj.BehaviorTypeVO;
import zack.project.domain.rebate.model.valobj.DailyBehaviorRebateVO;
import zack.project.infrastructure.event.EventPublisher;
import zack.project.infrastructure.persistent.dao.IDailyBehaviorRebateDao;
import zack.project.infrastructure.persistent.dao.ITaskDao;
import zack.project.infrastructure.persistent.dao.IUserBehaviorRebateOrderDao;
import zack.project.infrastructure.persistent.po.DailyBehaviorRebate;
import zack.project.infrastructure.persistent.po.Task;
import zack.project.infrastructure.persistent.po.UserBehaviorRebateOrder;

import cn.bugstack.middleware.db.router.strategy.IDBRouterStrategy;
import zack.project.types.enums.ResponseCode;
import zack.project.types.exception.AppException;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;

import java.util.List;


/**
 * @author A1793
 */
@Repository
@Slf4j
public class BehaviorRebateRepository implements IBehaviorRebateRepository {

    @Resource
    private IDailyBehaviorRebateDao dailyBehaviorRebateDao;
    @Resource
    private IUserBehaviorRebateOrderDao userBehaviorRebateOrderDao;
    @Resource
    private ITaskDao taskDao;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private EventPublisher eventPublisher;
    @Resource
    private IDBRouterStrategy dbRouter;


    @Override
    public List<DailyBehaviorRebateVO> queryDailyBehaviorRebateConfig(BehaviorTypeVO behaviorTypeVO) {

        List<DailyBehaviorRebate> dailyBehaviorRebates = dailyBehaviorRebateDao.
                queryDailyBehaviorRebateByBehaviorType(behaviorTypeVO.getCode());

        List<DailyBehaviorRebateVO> dailyBehaviorRebateVOS = new ArrayList<>(dailyBehaviorRebates.size());

        for (DailyBehaviorRebate dailyBehaviorRebate : dailyBehaviorRebates) {
            dailyBehaviorRebateVOS.add(DailyBehaviorRebateVO.builder().
                    rebateConfig(dailyBehaviorRebate.getRebateConfig()).
                    behaviorType(dailyBehaviorRebate.getBehaviorType()).
                    rebateDesc(dailyBehaviorRebate.getRebateDesc()).
                    rebateType(dailyBehaviorRebate.getRebateType()).
                    build());
        }
        return dailyBehaviorRebateVOS;
    }

    /**
     * 保存返利单和返利补偿任务
     * 并向SendRebateMessageEvent.RebateMessage监听的消息队列发送返利消息
     * @param userId
     * @param behaviorRebateAggregates
     */
    @Override
    public void saveUserRebateRecord(String userId, List<BehaviorRebateAggregate> behaviorRebateAggregates) {
        try {
            dbRouter.doRouter(userId);
            transactionTemplate.execute(status -> {
                try {
                    for (BehaviorRebateAggregate behaviorRebateAggregate : behaviorRebateAggregates) {
                        //获取返利单
                        BehaviorRebateOrderEntity behaviorRebateOrderEntity = behaviorRebateAggregate.
                                getBehaviorRebateOrderEntity();
                        //构建返利单的po对象，更新库表{user_behavior_rebate_order}
                        UserBehaviorRebateOrder userBehaviorRebateOrder = new UserBehaviorRebateOrder();
                        userBehaviorRebateOrder.setUserId(behaviorRebateOrderEntity.getUserId());
                        userBehaviorRebateOrder.setOrderId(behaviorRebateOrderEntity.getOrderId());
                        userBehaviorRebateOrder.setBehaviorType(behaviorRebateOrderEntity.getBehaviorType());
                        userBehaviorRebateOrder.setRebateDesc(behaviorRebateOrderEntity.getRebateDesc());
                        userBehaviorRebateOrder.setRebateType(behaviorRebateOrderEntity.getRebateType());
                        userBehaviorRebateOrder.setRebateConfig(behaviorRebateOrderEntity.getRebateConfig());
                        userBehaviorRebateOrder.setBizId(behaviorRebateOrderEntity.getBizId());
                        userBehaviorRebateOrder.setOutBusinessNo(behaviorRebateOrderEntity.getOutBusinessNo());
                        userBehaviorRebateOrderDao.insert(userBehaviorRebateOrder);
                        //构建返利补偿任务po对象
                        TaskEntity taskEntity = behaviorRebateAggregate.getTaskEntity();
                        Task task = new Task();
                        task.setUserId(taskEntity.getUserId());
                        task.setTopic(taskEntity.getTopic());
                        task.setMessageId(taskEntity.getMessageId());
                        task.setMessage(JSON.toJSONString(taskEntity.getMessage()));
                        task.setState(taskEntity.getState().getCode());

                        taskDao.insert(task);
                    }
                    return 1;
                } catch (DuplicateKeyException e) {
                    status.setRollbackOnly();
                    log.error("写入返利记录，唯一索引冲突 userId: {}", userId, e);
                    throw new AppException(ResponseCode.INDEX_DUP.getCode(), ResponseCode.INDEX_DUP.getInfo());
                }
            });
        } finally {
            dbRouter.clear();
        }

        //一个聚合对象是由一笔返利单和对应返利补偿任务构成
        for (BehaviorRebateAggregate behaviorRebateAggregate : behaviorRebateAggregates) {
            TaskEntity taskEntity = behaviorRebateAggregate.getTaskEntity();
            Task task = new Task();
            task.setUserId(taskEntity.getUserId());
            task.setMessageId(taskEntity.getMessageId());
            try {
                //发送返利消息
                eventPublisher.publish(taskEntity.getTopic(), taskEntity.getMessage());
                //将返利任务状态设置为completed
                taskDao.updateTaskSendMessageCompleted(task);
            }catch (Exception e) {
                log.error("写入返利记录，发送MQ消息失败 userId: {} topic: {}", userId, task.getTopic());
                taskDao.updateTaskSendMessageFail(task);
            }
        }

    }

    @Override
    public List<BehaviorRebateOrderEntity> queryOrderByOutBusinessNo(String userId, String outBusinessNo) {

        // 1. 请求对象
        UserBehaviorRebateOrder userBehaviorRebateOrderReq = new UserBehaviorRebateOrder();
        userBehaviorRebateOrderReq.setUserId(userId);
        userBehaviorRebateOrderReq.setOutBusinessNo(outBusinessNo);
        List<UserBehaviorRebateOrder> userBehaviorRebateOrders =
                userBehaviorRebateOrderDao.queryOrderByOutBusinessNo(userBehaviorRebateOrderReq);
        List<BehaviorRebateOrderEntity> behaviorRebateOrderEntities = new ArrayList<>(userBehaviorRebateOrders.size());

        for(UserBehaviorRebateOrder userBehaviorRebateOrder  :userBehaviorRebateOrders){
            BehaviorRebateOrderEntity behaviorRebateOrderEntity = BehaviorRebateOrderEntity.builder()
                        .userId(userBehaviorRebateOrder.getUserId())
                        .orderId(userBehaviorRebateOrder.getOrderId())
                        .behaviorType(userBehaviorRebateOrder.getBehaviorType())
                        .rebateDesc(userBehaviorRebateOrder.getRebateDesc())
                        .rebateType(userBehaviorRebateOrder.getRebateType())
                        .rebateConfig(userBehaviorRebateOrder.getRebateConfig())
                        .bizId(userBehaviorRebateOrder.getBizId())
                        .build();
            behaviorRebateOrderEntities.add(behaviorRebateOrderEntity);
        }
        return behaviorRebateOrderEntities;
    }
}

